home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
src
/
dd
/
menu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
27KB
|
922 lines
/*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*/
#include "defs.h"
#include "dbug_protos.h"
Prototype BOOL enable_menus(void);
Prototype void init_default_menus(void);
Prototype void free_menus(void);
Prototype void set_menu_item(int num, int type, unsigned char *str, unsigned char *cmd, unsigned char *comkey);
Prototype void do_scroller(void);
Prototype UWORD FindScrollerTop(UWORD total, UWORD displayable, UWORD pot);
Prototype int FindScrollerValues(UWORD total, UWORD displayable, UWORD top, WORD overlap, UWORD *body, UWORD *pot);
Prototype void setscrollbar(int flag);
Prototype void ActivateArrows(struct Window *win);
Prototype void InActivateArrows(struct Window *win);
Prototype BOOL ProcessMenuItem(char *args,int type);
Prototype int FindSlot(char *args);
#define MAXMENU 128 /* Maxumum number of user menus */
#define GADTOOLSBASE GadToolsBase
struct Menu *DebugMenu = NULL;
struct NewMenu newmenu[MAXMENU];
int MenuFlag = 0;
unsigned long ScrollStart = 0xffffffff;
unsigned long ScrollEnd = 0;
int SymbolCount;
struct InitMenu {
int type;
int num;
unsigned char *str;
unsigned char *cmd;
unsigned char *comkey;
};
#define NM_BAR 4
struct InitMenu IMenu[] = {
NM_TITLE, 1, "Project", "",NULL,
NM_ITEM, 1, "New", "reset",NULL,
NM_BAR, 1, "", "",NULL,
NM_ITEM, 1, "Open", "open",NULL,
NM_SUB, 1, "Source", "open source",NULL,
NM_SUB, 1, "Mixed", "open mixed",NULL,
NM_SUB, 1, "Dism", "open dism",NULL,
NM_SUB, 1, "Bytes", "open bytes",NULL,
NM_SUB, 1, "Symbols", "open symbols",NULL,
NM_SUB, 1, "Sorted symbols", "open symlist",NULL,
NM_SUB, 1, "Breakpoints", "open breakpoints",NULL,
NM_ITEM, 1, "Close", "close","C",
NM_BAR, 1, "", "",NULL,
NM_ITEM, 1, "Save Prefs", "saveprefs",NULL,
NM_BAR, 1, "", "",NULL,
NM_ITEM, 1, "Quit", "quit","Q",
NM_TITLE, 2, "Display", "",NULL,
NM_ITEM, 2, "Source", "source","S",
NM_ITEM, 2, "Mixed", "mixed","M",
NM_ITEM, 2, "Dism", "dism","D",
NM_ITEM, 2, "Bytes", "bytes","B",
NM_ITEM, 2, "Words", "words","W",
NM_ITEM, 2, "Longs", "longs","L",
NM_ITEM, 2, "Registers", "registers","R",
NM_ITEM, 2, "Offsets", "offsets",NULL,
NM_TITLE, 3, "Program Info", "",NULL,
NM_ITEM, 3, "Info on task", "info",NULL,
NM_ITEM, 3, "Hunks", "hunks",NULL,
NM_ITEM, 3, "Symbols", "symbols",NULL,
NM_ITEM, 3, "Sorted symbols", "symlist",NULL,
NM_TITLE, 4, "System Info", "",NULL,
NM_ITEM, 14, "Tasks", "tasks","",
NM_ITEM, 15, "Libraries", "libs","",
NM_ITEM, 15, "Devices", "devices","",
NM_ITEM, 16, "ExecBase", "execbase","",
NM_ITEM, 18, "DosBase", "dosbase",NULL,
NM_ITEM, 19, "Memory", "memlist",NULL,
NM_ITEM, 19, "Interrupts", "intrs",NULL,
NM_ITEM, 19, "Ports", "ports",NULL,
NM_ITEM, 19, "Resource", "resources",NULL,
NM_ITEM, 11, "Process", "process",NULL,
NM_TITLE, 13, "Breakpoints", "",NULL,
NM_ITEM, 19, "Breakpoints", "breakpoints",NULL,
NM_ITEM, 19, "Clear Breakpoint", "clear",NULL,
NM_ITEM, 19, "Clear All", "clear all",NULL,
NM_ITEM, 19, "Set Breakpoint", "bp",NULL,
NM_TITLE, 13, "Watchpoints", "",NULL,
NM_ITEM, 22, "Watch Byte", "watchbyte",NULL,
NM_ITEM, 22, "Watch Word", "watchword",NULL,
NM_ITEM, 22, "Watch Long", "watchlong",NULL,
NM_TITLE, 21, "Misc", "",NULL,
NM_ITEM, 22, "Help", "help",NULL,
NM_ITEM, 22, "REXX Command", "rexx",NULL,
NM_ITEM, 22, "Alias", "alias",NULL,
NM_ITEM, 22, "Unalias", "unalias",NULL,
NM_ITEM, 22, "Fkey", "fkey",NULL,
NM_ITEM, 22, "Set", "set",NULL,
NM_END, 23, "" , "", NULL
};
// Initialize default DD menus
void init_default_menus(void)
{
int i;
if(!MenuFlag) { // default menus not set
MenuFlag = TRUE;
memset((char *)newmenu,NM_END,sizeof(newmenu));
for(i=0; i< MAXMENU; i++) {
set_menu_item(i,IMenu[i].type,IMenu[i].str,IMenu[i].cmd,IMenu[i].comkey);
if(IMenu[i].type == NM_END)return;
}
}
}
// handle argument parsing for setting a menu item
BOOL ProcessMenuItem(char *args,int type)
{
char *ptr, *string, *dp;
char xname[3][80];
int n, i = 0, quote = 1, flag = TRUE, iflag;
memset(xname[1],0,80); /* zero the optionals */
memset(xname[2],0,80);
if(string = strchr(args,' ')) { // slot first, no sense in continuing without that
*string++ = NULL;
if((n = FindSlot(args)) < 0)return FALSE; // no slot available
string = SkipBlanks(string);
ptr = string;
while (flag && (i < 3)) {
iflag = 1;
dp = xname[i++];
while(*ptr && iflag) {
switch((int) *ptr) {
case '\"':
quote *= -1;
break;
case '\t':
case ' ':
if(quote > 0) {
iflag = 0; // not in quotes
break;
}
// fall through
default:
*dp++ = *ptr; //++;
}
ptr++;
}
*dp = NULL; // terminate the string
if(! *ptr)flag = FALSE; // done with args
}
if(i) {
set_menu_item(n, type, xname[0], xname[1], xname[2]);
return(TRUE);
}
}
return FALSE;
}
int FindSlot(char *args)
{
int n;
if((n = strtol(args,NULL,10)) >= 0 && (n < MAXMENU))return n; // normal slot specified
if(n == -1) { // its an append operation
for(n=0; n < (MAXMENU-1); n++)if(newmenu[n].nm_Type == NM_END) {
set_menu_item(n+1,NM_END,"","",""); // add the new end marker
return n;
}
}
ScrStatus("*** Error: can't find position");
return -1;
}
// enable current set of menus
BOOL enable_menus(void)
{
DBugDisp *disp;
BOOL flag = FALSE;
struct VisualInfo *vi;
struct TagItem taglist[3] = {
{GTMN_FrontPen, NULL},
{GTMN_FullMenu, TRUE},
{TAG_DONE, NULL}
};
// clear all menus from active windows on display list
for (disp = (DBugDisp *)DisplayList.lh_Head; disp->ds_Node.ln_Succ; disp = (DBugDisp *)disp->ds_Node.ln_Succ) {
if(disp->ds_Win)ClearMenuStrip(disp->ds_Win);
}
if(GADTOOLSBASE) {
if (DebugMenu != NULL) {
FreeMenus(DebugMenu);
DebugMenu = NULL;
}
if (!(DebugMenu = CreateMenusA(newmenu, taglist)))return 0;
if ((vi = GetVisualInfoA((CurDisplay->ds_Win)->WScreen, taglist+1))) {
if (!LayoutMenusA(DebugMenu, vi, taglist+1)) {
FreeVisualInfo(vi);
return 0;
}
}
FreeVisualInfo(vi);
}
else { // gadtools unavailable, so lets do it ourself
if (DebugMenu != NULL) {
v_free_menus(DebugMenu);
DebugMenu = NULL;
}
if(!(DebugMenu = v_create_menus(newmenu)))return 0;
if(!v_layout_menus(DebugMenu))return 0;
}
// Set the menu strips for active windows
for (disp = (DBugDisp *)DisplayList.lh_Head; disp->ds_Node.ln_Succ; disp = (DBugDisp *)disp->ds_Node.ln_Succ) {
if(disp->ds_Win)SetMenuStrip(disp->ds_Win, DebugMenu);
}
// and for current window (possibly not on display list yet)
if(CurDisplay && CurDisplay->ds_Win)
flag = (BOOL)SetMenuStrip(CurDisplay->ds_Win, DebugMenu);
return flag;
}
/***
*
* Set up a menu item to a given string and command
*
***/
void set_menu_item(int num, int type, unsigned char *str, unsigned char *cmd,
unsigned char *comkey)
{
DBugDisp *disp;
if (num < 0 || num >= MAXMENU) {
return;
}
// shutdown all menu items from active windows until they next do an enable
for (disp = (DBugDisp *)DisplayList.lh_Head; disp->ds_Node.ln_Succ; disp = (DBugDisp *)disp->ds_Node.ln_Succ) {
if(disp->ds_Win)ClearMenuStrip(disp->ds_Win);
}
/* First we free up any menu item that might be there */
if (newmenu[num].nm_UserData != NULL) {
free(newmenu[num].nm_UserData);
newmenu[num].nm_UserData = NULL;
}
if ((newmenu[num].nm_Label != NULL) && (newmenu[num].nm_Label != NM_BARLABEL)) {
free(newmenu[num].nm_Label);
newmenu[num].nm_Label = NULL;
}
if (newmenu[num].nm_CommKey != NULL) {
free(newmenu[num].nm_CommKey);
newmenu[num].nm_CommKey = NULL;
}
newmenu[num].nm_UserData=(void *)malloc(strlen(cmd)+8);
newmenu[num].nm_Label= (type == 4) ? NM_BARLABEL: malloc(strlen(str)+8);
if(comkey && *comkey) {
newmenu[num].nm_CommKey=(void *)malloc(strlen(comkey)+8);
}
if((newmenu[num].nm_UserData == NULL)|| (newmenu[num].nm_Label==NULL) ||
((comkey && *comkey) && (newmenu[num].nm_CommKey == NULL))) {
newmenu[num].nm_Type = 0;
return; /* out of memory */
}
strcpy(((char *)newmenu[num].nm_UserData), cmd);
if (type == 4) type = 2;
else strcpy(newmenu[num].nm_Label,str);
newmenu[num].nm_Type = type;
newmenu[num].nm_Flags = 0;
if(comkey && *comkey)strcpy(((char *)newmenu[num].nm_CommKey), comkey);
else newmenu[num].nm_CommKey = 0;
}
/* Free up all menu storage */
void free_menus(void)
{
int i;
if (DebugMenu != NULL) {
if(GADTOOLSBASE)FreeMenus(DebugMenu);
else v_free_menus(DebugMenu);
DebugMenu = NULL;
}
for (i = 0; i < MAXMENU; i++) {
if (newmenu[i].nm_UserData != NULL)free(newmenu[i].nm_UserData);
if ((newmenu[i].nm_Label != NULL) && (newmenu[i].nm_Label != NM_BARLABEL))free(newmenu[i].nm_Label);
if (newmenu[i].nm_CommKey != NULL)free(newmenu[i].nm_CommKey);
newmenu[i].nm_UserData = NULL;
newmenu[i].nm_Label = NULL;
newmenu[i].nm_CommKey = NULL;
}
}
extern struct Gadget ColorGadget;
extern struct Gadget DownGadget;
extern struct Gadget UpGadget;
extern struct Image ColorPropImage;
extern struct PropInfo ColorPropInfo;
/* Set size of scroll bar. If flag is true, remove the scroll bar first */
void setscrollbar(int flag)
{
WINDOW *win;
if(CurDisplay) {
if((win = CurDisplay->ds_Win)) {
if(flag)RemoveGadget(win,&ColorGadget);
else { /* first time through */
AddGadget(win,&UpGadget,(UWORD)~0);
AddGadget(win,&DownGadget,(UWORD)~0);
}
}
}
/* Set up the scroll bar */
ColorGadget.LeftEdge = - win->BorderRight + 4;
ColorGadget.TopEdge = win->BorderTop;
ColorGadget.Height=win->Height - win->BorderBottom - win->BorderTop-8 - 22;
ColorGadget.Width= 14; /* win->BorderRight-3; */
ColorPropInfo.VertBody = 0xFFFF; /* starts with nothing */
AddGadget(win,&ColorGadget,(UWORD)~0);
RefreshGadgets(&UpGadget,win,NULL); /* refresh just the scroll bar */
}
int FindScrollerValues(UWORD total, UWORD displayable, UWORD top,
WORD overlap, UWORD *body, UWORD *pot)
{
// UWORD hidden;
int hidden;
UWORD oldbody = *body;
UWORD oldpot = *pot;
int temp1 = total, temp2 = displayable;
hidden = MAX(temp1-temp2, 0);
if(top > hidden)top = hidden;
(*body) = (hidden > 0) ? (UWORD)(((ULONG)(displayable - overlap)*MAXBODY)
/ (total - overlap)) : MAXBODY;
(*pot) = (hidden > 0) ? (UWORD) (((ULONG)top * MAXPOT)/hidden) : 0;
if((oldbody == *body) && (oldpot == *pot))return(FALSE);
return(TRUE);
}
UWORD FindScrollerTop(UWORD total, UWORD displayable, UWORD pot)
{
//UWORD top, hidden;
int top, hidden;
int temp1 = total, temp2 = displayable;
hidden = MAX(temp1-temp2, 0);
top = ((((ULONG) hidden * pot) + (MAXPOT/2)) >> 16); /* range from 0 to ... */
return(top);
}
void do_scroller(void)
{
WINDOW *win;
ULONG total, top;
int rows;
if(CurDisplay) {
if((win = CurDisplay->ds_Win)) {
rows = CurDisplay->ds_ScrRows;
// calc new values
top = CurDisplay->ds_WindowTop; // current top for almost all display modes
switch(CurDisplay->ds_DisplayMode) {
case DISPLAY_DISM:
case DISPLAY_SOURCE:
case DISPLAY_MIXED:
case DISPLAY_BYTES:
case DISPLAY_WORDS:
case DISPLAY_LONGS:
total = (ScrollEnd - ScrollStart) >> 5;
top = ((int)CurDisplay->ds_WindowTop - (int)ScrollStart) >> 5;
if((int)top < 0 ) top = 0;
break;
case DISPLAY_SYMBOL:
total = SymbolCount;
break;
case DISPLAY_HUNKS:
total = numHunks;
break;
case DISPLAY_HELP:
total = HelpSize();
break;
case DISPLAY_BREAK:
total = MAXBP+5;
top = topBP;
break;
default:
total = SizeDLIST(&CurDisplay->ds_List);
}
if(FindScrollerValues(total, CurDisplay->ds_ScrRows, top, 2,
&ColorPropInfo.VertBody,&ColorPropInfo.VertPot)) {
/* values changed, update */
NewModifyProp(&ColorGadget,win,NULL,PROPNEWLOOK | AUTOKNOB | FREEVERT,0,
ColorPropInfo.VertPot, 0, ColorPropInfo.VertBody, -1 );
}
}
}
}
__chip const UWORD upPicture[] =
{
/* Plane 0 */
0x0000,0x0000,0x0000,0x0000,0x0180,0x0660,0x1818,0x0000,
0x0000,0x0000,0xFFFF,
/* Plane 1 */
0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
};
__chip const UWORD upPictureSelect[] =
{
/* Plane 0 */
0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
0xFFFF,0xFFFF,0xFFFF,
/* Plane 1 */
0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFE7F,0xF99F,0xE7E7,0xFFFF,
0xFFFF,0xFFFF,0x0000,
};
__chip const UWORD downPicture[] =
{
/* Plane 0 */
0x0000,0x0000,0x0000,0x0000,0x1818,0x0660,0x0180,0x0000,
0x0000,0x0000,0xFFFF,
/* Plane 1 */
0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,
};
__chip const UWORD downPictureSelect[] =
{
/* Plane 0 */
0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
0xFFFF,0xFFFF,0xFFFF,
/* Plane 1 */
0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE7E7,0xF99F,0xFE7F,0xFFFF,
0xFFFF,0xFFFF,0x0000,
};
struct Image UpImage = {
-1, 0, /* Left, Top */
16, 11, 2, /* width, depth, height */
upPicture,
3, 0, /* PlanePick, PlaneOnOff */
NULL
};
struct Image DownImage = {
-1, 0, /* Left, Top */
16, 11, 2, /* width, height, depth */
downPicture,
3, 0, /* PlanePick, PlaneOnOff */
NULL
};
struct Image UpImageSelect = {
-1, 0, /* Left, Top */
16, 11, 2, /* width, depth, height */
upPictureSelect,
3, 0, /* PlanePick, PlaneOnOff */
NULL
};
struct Image DownImageSelect = {
-1, 0, /* Left, Top */
16, 11, 2, /* width, height, depth */
downPictureSelect,
3, 0, /* PlanePick, PlaneOnOff */
NULL
};
struct Gadget UpGadget = {
NULL, /* NextGadget */
-15, -31, /* gadget hit box LeftEdge, TopEdge */
16, 11, /* gadget hit box Width, Height */
GADGHCOMP|GADGIMAGE|GRELRIGHT|GRELBOTTOM|RIGHTBORDER, /* Flags */
RELVERIFY|GACT_IMMEDIATE, /* Activation */
BOOLGADGET, /* GadgetType */
&UpImageSelect, /* GadgetRender */
NULL, /* no SelectRender */
NULL, /* no text for this gadget */
NULL, /* no MutualExclude */
NULL, /* no SpecialInfo */
ID_UP, /* gadget ID */
NULL /* no general purpose data */
};
struct Gadget DownGadget = {
NULL, /* NextGadget */
-15, -20, /* gadget hit box LeftEdge, TopEdge */
16, 11, /* gadget hit box Width, Height */
GADGHCOMP|GADGIMAGE|GRELRIGHT|GRELBOTTOM|RIGHTBORDER, /* Flags */
RELVERIFY|GACT_IMMEDIATE, /* Activation */
BOOLGADGET, /* GadgetType */
&DownImageSelect, /* GadgetRender */
NULL, /* no SelectRender */
NULL, /* no text for this gadget */
NULL, /* no MutualExclude */
NULL, /* no SpecialInfo */
ID_DOWN, /* gadget ID */
NULL /* no general purpose data */
};
/* scroller gadgets */
#define COLOR_KNOB_BODY 0x1111
struct Image ColorPropImage;
struct PropInfo ColorPropInfo = {
PROPNEWLOOK | AUTOKNOB | FREEVERT, /* flags */
0, /* horiz pot */
0xFFFF, /* vert pot */
0, /* horiz body */
0, /* vert body */
0, 0, /* cwidth, cheight */
0, 0, /* HpotRes, VPotRes */
0, 0 /* Left border, Top border */
};
struct Gadget ColorGadget = {
NULL, /* Next gadget */
-10, /* leftedge */
4, /* top edge */
10, /* width */
80, /* height */
GADGHCOMP|GADGIMAGE|GRELRIGHT|RIGHTBORDER, /* flags */
FOLLOWMOUSE|GACT_IMMEDIATE, /* activation */
PROPGADGET, /* gadget type */
&ColorPropImage, /* gadget render */
NULL, /* select render */
NULL, /* gadget text */
NULL, /* custom gadget hook */
&ColorPropInfo, /* special info */
ID_SCROLL, /* gadget ID */
NULL /* user data */
};
void ActivateArrows(struct Window *win)
{
int pos;
pos = RemoveGadget(win,&UpGadget);
UpGadget.GadgetRender = &UpImageSelect;
AddGadget(win,&UpGadget,pos);
pos = RemoveGadget(win,&DownGadget);
DownGadget.GadgetRender = &DownImageSelect;
AddGadget(win,&DownGadget,pos);
// refresh gadgets in do_scroller
setscrollbar(1);
do_scroller();
}
void InActivateArrows(struct Window *win)
{
int pos;
pos = RemoveGadget(win,&UpGadget);
UpGadget.GadgetRender = &UpImage;
AddGadget(win,&UpGadget,pos);
pos = RemoveGadget(win,&DownGadget);
DownGadget.GadgetRender = &DownImage;
AddGadget(win,&DownGadget,pos);
RefreshGadgets(&UpGadget,win,NULL); /* refresh just the scroll bar */
}
Prototype struct Menu *v_create_menus(struct NewMenu *menulist);
Prototype int v_layout_menus(struct Menu *menus);
Prototype void v_free_menus(struct Menu *menus);
Prototype int text_width(char *str);
Local void *malloc_clear(ULONG bytes);
struct TextAttr TOPAZ80={"topaz.font",8,0,FPF_ROMFONT};
void *malloc_clear(ULONG bytes) {
void *ptr = malloc(bytes);
if(ptr)memset(ptr,0,bytes);
return ptr;
}
struct XMenu {
struct Menu menu;
APTR userdata;
struct Image image;
};
struct XItem {
struct MenuItem item;
APTR userdata;
struct IntuiText itext;
};
#define VBAR 2 /* Pixel width of a vertical BAR */
#define DVBAR (2*VBAR) /* Pixel width of two vertical BARs */
#define HBAR 1 /* Pixel height of a horizontal BAR */
#define DHBAR (2*HBAR) /* Pixel height of two Horizontal BARs */
/***********************************************************************************
* Procedure: create_menus
* Synopsis: Menu = create_menus(NewMenu);
* Purpose: Create the appropriate menu structures for a given NewMenu list
***********************************************************************************/
struct Menu *v_create_menus(struct NewMenu *menulist)
{
int i;
struct Menu *retmenu;
struct XMenu *thismenu;
struct XItem *thisitem;
static struct Image sep_image = {5, 1, 1000, 2,0, NULL, 0,0, NULL};
/* We don't have GadTools around to do the work for us, so just create the */
/* Menu structures directly. */
retmenu = NULL; /* Default to giving them NOTHING */
for (i = 0; i < MAXMENU; i++) {
switch (menulist[i].nm_Type) {
case NM_TITLE:
{
struct XMenu *newmenu;
newmenu = (struct XMenu *)malloc_clear(sizeof(struct XMenu));
if (newmenu == NULL) {
v_free_menus(retmenu);
return(NULL);
}
/* Link the menu structure onto the list of other menus */
if (retmenu == NULL)retmenu = &newmenu->menu;
else thismenu->menu.NextMenu = &newmenu->menu;
thismenu = newmenu;
}
thismenu->menu.Flags = MENUENABLED;
thismenu->menu.MenuName = menulist[i].nm_Label;
thismenu->userdata = menulist[i].nm_UserData;
thismenu->image = sep_image;
break;
case NM_ITEM:
case NM_SUB:
if (thismenu == NULL) return(NULL);
{
struct XItem *newitem;
newitem = (struct XItem *)malloc_clear(sizeof(struct XItem));
if (newitem == NULL) {
v_free_menus(retmenu);
return(NULL);
}
if (thismenu->menu.FirstItem == NULL)
thismenu->menu.FirstItem = &newitem->item;
else {
for(thisitem = (struct XItem *)thismenu->menu.FirstItem; thisitem->item.NextItem; thisitem = (struct XItem *)thisitem->item.NextItem)
;
thisitem->item.NextItem = &newitem->item;
}
thisitem = newitem;
}
if (menulist[i].nm_Label == NM_BARLABEL) {
thisitem->item.Flags = 0;
thisitem->item.ItemFill = &thismenu->image;
}
else {
/* fill in the intuitext with some reasonable defaults */
thisitem->itext.FrontPen = 0;
thisitem->itext.DrawMode = JAM1;
thisitem->itext.LeftEdge = 5;
thisitem->itext.TopEdge = 1;
thisitem->itext.ITextFont = &TOPAZ80;
thisitem->itext.IText = menulist[i].nm_Label;
thisitem->item.Flags = ITEMTEXT|ITEMENABLED|HIGHCOMP;
thisitem->item.ItemFill = (APTR)&thisitem->itext;
if (menulist[i].nm_CommKey) {
thisitem->item.Command = *menulist[i].nm_CommKey;
thisitem->item.Flags |= COMMSEQ;
}
}
thisitem->userdata = menulist[i].nm_UserData;
break;
case NM_END:
return(retmenu);
}
}
return(retmenu);
}
/***********************************************************************************
* Procedure: layout_menus
* Synopsis: rc = layout_menus(Menu);
* Purpose: Lays out a menu given the current global information
***********************************************************************************/
int v_layout_menus(struct Menu *menus)
{
struct XMenu *menu;
struct XItem *item;
int xpos;
int swidth, sheight, stxheight;
xpos = VBAR;
// get screen width and height for later
if(CurDisplay && CurDisplay->ds_Win) {
swidth = CurDisplay->ds_Win->WScreen->Width;
sheight = CurDisplay->ds_Win->WScreen->Height;
stxheight = CurDisplay->ds_Win->RPort->TxHeight;
}
else {
swidth = 640;
sheight = 200;
stxheight = 8;
}
for (menu = (struct XMenu *)menus; menu; menu = (struct XMenu *)menu->menu.NextMenu) {
int width, ypos;
/* set the x position of the menu to the next available position.
* Set the menu width based on the size of the text.
*/
menu->menu.LeftEdge = xpos;
menu->menu.Width = text_width(menu->menu.MenuName) + DVBAR;
/* set the initial item y-position to just below the title bar */
ypos = 0;
/* walk through the list of items for the first pass. The object
* is to find the width of the largest item. We will also set
* the y-position of each item on this pass.
*/
width = menu->menu.Width; /* make items at least as big as menu */
for (item = (struct XItem *)menu->menu.FirstItem; item; item = (struct XItem *)item->item.NextItem) {
int iwidth = 0;
/* set the y-position of the item to the next available. Also,
* put the item just to the left of the menu. You can make
* this number zero if you prefer.
*/
item->item.TopEdge = ypos;
item->item.LeftEdge = -VBAR;
/* if it's a text item, see how big it is. */
if (item->item.Flags & ITEMTEXT) {
struct IntuiText *itext;
itext = (struct IntuiText *)item->item.ItemFill;
/* the height is just the font height + 2. The width is
* based on the string pixel width.
*/
item->item.Height = 2 + stxheight;
iwidth = text_width(itext->IText) + 10;
/* if it has a command-key sequence, then add in the space needed
* for the command key and the command symbol. Note that in
* lo-res, we should actually use LOWCOMMWIDTH, but I'm
* feeling lazy today.
*/
if (item->item.Flags & COMMSEQ) {
char buf[2];
buf[0] = item->item.Command;
buf[1] = 0;
iwidth += text_width(buf) + COMMWIDTH + 8;
}
}
else {
/* separator bars are always the same height */
item->item.Height = 4;
}
/* update the y-position variable. Make sure the items don't
* run off the bottom.
*/
ypos += item->item.Height;
if (ypos >= (sheight - DHBAR))return 0;
/* now see if this item is the largest one. */
if (iwidth > width) width = iwidth;
}
/* on our second pass, we set the widths of all the items to the
* width of the largest item so that it looks good. In addition,
* we are going to adjust menus that might run off the right edge.
*/
for (item = (struct XItem *)menu->menu.FirstItem; item; item = (struct XItem *)item->item.NextItem) {
item->item.Width = width;
if ((xpos + width) >= (swidth - 2))item->item.LeftEdge = swidth - 2 - xpos - width;
}
menu->image.Width = width - 7;
/* now update the x position variable, make sure that the menu
* header is not off the edge of the screen, and add a little space
* between the headers. Feel free to make this number whatever
* you want. If you are feeling really ambitious, you could
* make this number adaptable.
*/
xpos += menu->menu.Width;
if (xpos > swidth) return(NULL);
xpos += 8;
}
return(TRUE);
}
/***********************************************************************************
* Procedure: v_free_menus
* Synopsis: v_free_menus(Menu);
* Purpose: Return any storage allocated for a given Menu structure.
***********************************************************************************/
void v_free_menus(struct Menu *menus)
{
struct XMenu *menu, *nextmenu;
struct XItem *item, *nextitem;
for (menu = (struct XMenu *)menus; menu; menu = nextmenu) {
nextmenu = (struct XMenu *)menu->menu.NextMenu;
for (item = (struct XItem *)menu->menu.FirstItem; item; item = nextitem) {
nextitem = (struct XItem *)item->item.NextItem;
free(item);
}
free(menu);
}
}
/***********************************************************************************
* Procedure: text_width
* Synopsis: len = text_width(str)
* Purpose: Return the rendered width of a given string
***********************************************************************************/
int text_width(char *str)
{
struct IntuiText itext;
itext.FrontPen = 1;
itext.BackPen = 0;
itext.DrawMode = JAM1;
itext.LeftEdge = 0;
itext.TopEdge = 1;
itext.ITextFont = &TOPAZ80; // replace with actual font
itext.NextText = NULL;
itext.IText = str;
return(IntuiTextLength(&itext));
}